package com.ruoyi.framework.scanpath;

import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.common.core.redis.RedisCache;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 项目中 请求 url工具
 *
 * @author yql
 */
public class ScanPathUtils {

    private static WebApplicationContext applicationContext;

    private static final RedisCache redis = SpringUtil.getBean(RedisCache.class);

    private static final String key = "url:";

    /**
     * 项目初始化
     */
    public static void init(WebApplicationContext applicationContext) {
        ScanPathUtils.applicationContext = applicationContext;
        clearList();
        cacheList(initList());
    }

    /**
     * 清理历史缓存
     */
    private static void clearList() {
        getKeys().forEach(redis::deleteObject);
    }

    /**
     * 缓存url到redis中
     *
     * @param list 列表
     */
    private static void cacheList(List<UrlModel> list) {
        for (UrlModel urlModel : list) {
            redis.setCacheObject(getKey(urlModel), urlModel);
        }
    }

    /**
     * 获取存储的key
     *
     * @param urlModel 对象
     * @return 存储的key
     */
    private static String getKey(UrlModel urlModel) {
        return getKey(urlModel.getUrl(), urlModel.getMethod());
    }

    /**
     * 获取到 key
     *
     * @param url    请求url
     * @param method 请求方式
     * @return 对应存储的key
     */
    public static String getKey(String url, String method) {
        return key + url + ":" + method;
    }

    public static UrlModel getOne(String url, String method) {
        String key1 = getKey(url, method);
        if (redis.hasKey(key1)) {
            return (UrlModel) redis.getCacheObject(key1);
        }
        return null;
    }

    /**
     * 获取项目中所有的url
     *
     * @return 所有url
     */
    private static List<UrlModel> initList() {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();


        List<UrlModel> list = new ArrayList<>();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> m : map.entrySet()) {
            UrlModel urlModel = new UrlModel();
            RequestMappingInfo info = m.getKey();
            PatternsRequestCondition p = info.getPatternsCondition();
            if (p == null) {
                continue;
            }
            for (String url : p.getPatterns()) {
                urlModel.setUrl(url);
            }
            RequestMethodsRequestCondition methodsCondition = info.getMethodsCondition();
            for (RequestMethod requestMethod : methodsCondition.getMethods()) {
                urlModel.setMethod(requestMethod.toString());
            }

            list.add(urlModel);
        }
        return list;
    }

    /**
     * 获取所有url
     *
     * @return 所有url
     */
    public static List<UrlModel> getList() {
        return getKeys().stream().map(data -> (UrlModel) redis.getCacheObject(data)).collect(Collectors.toList());
    }

    /**
     * 获取key列表
     *
     * @return key列表
     */
    private static Collection<String> getKeys() {
        return redis.keys(key + "*").stream().map(data -> data.replace(SpringUtil.getProperty("ruoyi.name")+":", "")).collect(Collectors.toList());
    }


}
